home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianNetDaemon.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  33KB  |  1,599 lines

  1. /* ScianNetDaemon.c John R. Murray 1-19-92
  2.  */
  3.  
  4. /* BSD_SIGS or SYSV_SIGS */
  5.  
  6. #ifdef PAUSE
  7. #ifdef BSD_SIGS
  8. #define _BSD_SIGNALS
  9. #endif
  10. #include <signal.h>
  11. #include <stropts.h>
  12. #endif /* def PAUSE */
  13.  
  14. #include "machine.h"
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <sys/types.h>
  19. #include <unistd.h>
  20. #include <sys/wait.h>
  21. #include <errno.h>
  22.  
  23. #if MACHINE == IRIS4D
  24. #include <sys/prctl.h>
  25. #endif
  26.  
  27. #if MACHINE == CONVEX
  28. #include <time.h>
  29. #endif
  30.  
  31. #include <sys/socket.h>
  32. #include <netinet/in.h>
  33. #include <netdb.h>
  34. #include <fcntl.h>
  35. #include <string.h>
  36. #include <sys/times.h>
  37. #include <sys/param.h>
  38.  
  39. #if MACHINE == CRAYYMP
  40. #include <time.h>
  41. #endif
  42.  
  43. #include "ScianNetDaemon.h"
  44.  
  45. #define PERROR
  46.  
  47. /* to avoid having to include lots of Scian include files */
  48. #define ICONUNKNOWN     61
  49.  
  50. /* if you don't know how to pronounce "Daemon", listen to the beginning of
  51.  * the first song on the first side of _Locust Abortion Technician_ by
  52.  * the Butthole Surfers. Really loud. Really, really loud.
  53.  */
  54.  
  55. #define true 1
  56. #define false 0
  57.  
  58. /*Values for socketState*/
  59. #define NOTLISTENING    0    /*Not even listening for a connection*/
  60. #define LISTENING    1    /*Socket is listening for a connection*/
  61. #define VALIDATING    2    /*Socket is connected*/
  62. #define CONNECTED    3    /*Have gotten a good initial inquiry*/
  63. #define TRANSFERRING    4    /*transferring connection to a scian process*/
  64.  
  65. #define NULLFILED    -1
  66.  
  67. #define MYBUFSIZ 1024        /* size of local stream buffers */
  68.  
  69. #define IsMainConn(c) ((c) == mainConn)
  70. /* #define IsMainConn(c) ((c)->sockNum == baseSocketNumber)
  71. */
  72.  
  73. int lasterror;                /* tracks last system error */
  74.  
  75. #define ATTENTION_SPAN 30        /* start napping if  < idle time */
  76. #define DEFAULT_TIME_OUT (60 * 60)    /* default timeout one hour */
  77.  
  78. typedef double Time;
  79. /* timeOut = 0 means never time out */
  80. Time timeOut = DEFAULT_TIME_OUT;    /* no-activity timeout in seconds. */
  81. struct tms timesBuffer;            /* dummy for times() calls */
  82.  
  83. typedef struct ConnStruct {
  84.     int sockNum;        /* socket number this one is connected to */
  85.     int template;        /* socket template file descriptor */
  86.     int sock;            /* socket file descriptor */
  87.     int state;            /* state of socket */
  88.     int flags;            /* informational bits */
  89.     char buf[MYBUFSIZ];        /* stream input buffer */
  90.     int bufi;            /* index into stream buffer */
  91.     struct ConnStruct *next;
  92. } *ConnPtr;
  93.  
  94. typedef struct SLStruct {
  95.     /* int sockNum; */
  96.     ConnPtr conn;
  97.     struct SLStruct *next;
  98. } *SockListPtr;
  99.  
  100. typedef struct ORStruct {
  101.     unsigned long objectNum;
  102.     struct ORStruct *next;
  103.     int iconNum;
  104.     char objectName[1];
  105. } *ObjRecPtr;
  106.  
  107. typedef struct PStruct {
  108.     int procNum;
  109.     int sockNum;        /* process is listening on sockNum */
  110.     Time lastAccess;
  111.     ObjRecPtr objectList;
  112.     SockListPtr keepAdvised;
  113.     struct PStruct *next;
  114.     char procName[1];
  115. } ProcessStruct, *ProcessPtr;
  116.  
  117. ProcessPtr processes;
  118.  
  119. char tempStr[MYBUFSIZ];        /* temp Str. */
  120.  
  121. #define ND_FLAGS_KEEPADVISED 0x01
  122. #define ND_FLAGS_STREAMERROR 0x80
  123.  
  124. int socketBlockLength;    /* how many socket numbers to try */
  125. int baseSocketNumber;    /* port number that connections come in on */
  126.  
  127. int lastPort;        /* FindSocket keeps track of last socket number tried */
  128.  
  129. ConnPtr mainConn = (ConnPtr) 0;    /* primary listener */
  130. ConnPtr connList = (ConnPtr) 0;    /* list of secondary connections */
  131. int proto;            /* protocol num. returned by getprotobyname()*/
  132.  
  133. #ifdef PAUSE
  134. /* SIGIO signal handler */
  135.  
  136. int handlerCount = 0;
  137. int oldHandlerCount = 0;
  138.  
  139. sigIOHandler()
  140. {
  141.     ++handlerCount;
  142. #ifdef SYSV_SIGS
  143.     signal(SIGIO, sigIOHandler);
  144. #endif
  145. }
  146. #endif
  147.  
  148. #ifdef ALARM
  149. int alarmClock = 0;
  150. sigAlrmHandler()
  151. {
  152.     ++alarmClock;
  153. #ifdef SYSV_SIGS
  154.     signal(SIGALRM, sigAlrmHandler);
  155. #endif
  156. }
  157. #endif
  158.  
  159. int writen(fd, cptr, nbytes)
  160. int fd;
  161. char *cptr;
  162. int nbytes;
  163. {
  164.     int nleft, nwritten;
  165.  
  166.     nleft = nbytes;
  167.     while (nleft > 0)
  168.     {
  169.     nwritten = write(fd, cptr, nleft);
  170.     if (nwritten < 0)
  171.     {
  172.         perror("Uh-oh! writen");
  173.         return nwritten;
  174.     }
  175.     nleft -= nwritten;
  176.     cptr += nwritten;
  177.     }
  178. }
  179.  
  180. /*NewConn: creates a new connection record from the stream associated with it*/
  181. ConnPtr NewConn()
  182. {
  183.     ConnPtr retVal;
  184.  
  185.     retVal = malloc(sizeof(struct ConnStruct));
  186.     retVal -> bufi = 0;
  187.     retVal -> state = NOTLISTENING;
  188.     retVal -> flags = 0;
  189.     retVal -> sockNum = 0;
  190.     retVal -> next = (struct ConnStruct *) 0;
  191.     return retVal;
  192. }
  193.  
  194. int FindSocket(c)
  195. /* FindSocket looks for an open port. It returns 0 if successful, -1
  196.  * if failed. If the port number in the connection record (c->sockNum) is
  197.  * non-zero, FindSocket tries to open that port, and fails if it's not
  198.  * available. If c->sockNum is zero, FindSocket will search the possible
  199.  * port numbers until it successfully binds one.
  200.  */
  201. ConnPtr c;
  202. {
  203.     struct sockaddr_in templateAddr;    /*Socket template for listening*/
  204.     int any_port;
  205.     int first_tried;
  206.     int status;
  207.  
  208.     any_port = true;
  209.  
  210.     /* sanity check */
  211.     if (c->state != NOTLISTENING)
  212.     {
  213.     fprintf(stderr, "FindSocket sanity check! Bad state %d\n", c->state);
  214.     return -1;
  215.     }
  216.  
  217.     /* initialize */
  218.     if (c->sockNum != 0)
  219.     {
  220.     templateAddr . sin_port = htons((u_short) c->sockNum);
  221.     first_tried = c->sockNum;
  222.     any_port = false;
  223.     }
  224.     else
  225.     {
  226.     if (++lastPort >= baseSocketNumber + socketBlockLength)
  227.         lastPort = baseSocketNumber + 1;
  228.     templateAddr . sin_port = htons((u_short) lastPort);
  229.     first_tried = lastPort;
  230.     c->sockNum = lastPort;
  231.     }
  232.     templateAddr . sin_family = PF_INET;
  233.     templateAddr . sin_addr.s_addr = INADDR_ANY;
  234.  
  235.     c->template = socket(PF_INET, SOCK_STREAM, proto);
  236.     if (c->template < 0)
  237.     {
  238.     {
  239. #ifdef PERROR
  240.         perror("socket() in FindSocket");
  241. #endif
  242.         if (any_port) c->sockNum = 0;
  243.         return -1;
  244.     }
  245.     }
  246.  
  247. #ifdef PAUSE
  248.     /* ioctl(c->template, I_SETSIG, S_INPUT); */
  249.     fcntl(c->template, F_SETOWN, getpid());
  250.     fcntl(c->template, F_SETFL, fcntl(c->template, F_GETFL) | FASYNC);
  251.     if (!(fcntl(c->template, F_GETFL) & FASYNC))
  252.     fprintf(stderr, "template flag not set, Bub!\n");
  253. #endif
  254.  
  255.     status = -1;
  256.     while (status < 0)
  257.     {
  258. #ifdef DEBUG
  259.     fprintf(stderr, "trying to bind socket %d\n", ntohs(templateAddr.sin_port));
  260. #endif
  261.     status = bind(c->template, &templateAddr, sizeof(templateAddr));
  262.     if (status >= 0)
  263.     {
  264.         /*Name was bound OK*/
  265.  
  266.         /*Set socket to be non blocking*/
  267. #if CRAYYMP
  268.         fcntl(c->template, F_SETFL, 
  269.         fcntl(c->template, F_GETFL) | O_NDELAY);
  270.         fcntl(c->template, F_SETFL, 
  271.         fcntl(c->template, F_GETFL) | O_NONBLOCK);
  272. #else
  273.         fcntl(c->template, F_SETFL, 
  274.         fcntl(c->template, F_GETFL) | FNDELAY);
  275. #endif
  276.  
  277.         /*Listen for a maximum of 5 connections*/
  278.         if (listen(c->template, 5) < 0)
  279.         {
  280. #ifdef PERROR
  281.         perror("listen() in FindSocket");
  282. #endif
  283.         if (any_port) c->sockNum = 0;
  284.         close (c->template); c->template = -1;
  285.         return -1;
  286.         }
  287.     }
  288.     else
  289.     {
  290.         if (any_port && (errno == EADDRINUSE))
  291.         {
  292.         if (++lastPort >= baseSocketNumber+socketBlockLength)
  293.             lastPort = baseSocketNumber + 1;
  294.         templateAddr . sin_port = htons((u_short) lastPort);
  295.         c->sockNum = lastPort;
  296.         if (lastPort == first_tried)
  297.         {
  298.             /*went all the way through the block without finding one*/
  299.             fprintf(stderr, "No sockets open!\n");
  300.             if (any_port) c->sockNum = 0;
  301.             close (c->template); c->template = -1;
  302.             return -1;
  303.         }
  304.         }
  305.         else
  306.         {
  307. #ifdef PERROR
  308.         perror("bind() call failed in FindSocket");
  309. #endif
  310.         if (any_port) c->sockNum = 0;
  311.         close (c->template); c->template = -1;
  312.         return -1;
  313.         }
  314.     }
  315.     }
  316.     return 0;
  317. }
  318.  
  319. void CloseSocket(c)
  320. ConnPtr c;
  321. {
  322.     if (c->sock >= 0)
  323.     {
  324.     close(c->sock); c->sock = -1;
  325.     }
  326.     if (c->template >= 0)
  327.     {
  328.     close(c->template); c->template = -1;
  329.     }
  330.     c->bufi = 0;
  331.     c->state = NOTLISTENING;
  332. }
  333.  
  334. void CloseAll()
  335. {
  336.     ConnPtr runner;
  337.     CloseSocket(mainConn);
  338.  
  339.     runner = connList;
  340.     while(runner)
  341.     {
  342.     CloseSocket(runner);
  343.     runner = runner->next;
  344.     }
  345. }
  346.  
  347. void AddConnectionRecord(c)
  348. ConnPtr c;
  349. {
  350.     c -> next = connList;
  351.     connList = c;
  352. }
  353.  
  354. /* using the socket number, find the connection record for that socket */
  355. ConnPtr FindConnectionRecord(num)
  356. int num;
  357. {
  358.     ConnPtr runner;
  359.  
  360.     runner = connList;
  361.  
  362.     while(runner)
  363.     {
  364.     if (runner -> sockNum == num)
  365.     {
  366.         return runner;
  367.     }
  368.     runner = runner -> next;
  369.     }
  370.     return (ConnPtr) 0;
  371. }
  372.  
  373. void DeleteConnectionRecord(c)
  374. ConnPtr c;
  375. {
  376.     ConnPtr *runner;
  377.  
  378.     runner = &connList;
  379.     while (*runner)
  380.     {
  381.     if ((*runner) == c)
  382.     {
  383.         while (DoDeferredMessage()) /* What a hack! clear deferred msgs */
  384.         ;
  385.         (*runner) = (*runner) -> next;
  386.         free (c);
  387.         return;
  388.     }
  389.     runner = &((*runner) -> next);
  390.     }
  391. }
  392.  
  393. int strcmp2(s1, s2)
  394. char s1[], s2[];
  395. /*Compares s1 and s2 without regard to case*/
  396. {
  397.     int k;
  398.     for (k = 0; s1[k]; ++k)
  399.     {
  400.     if (toupper(s1[k]) < toupper(s2[k])) return -k - 1;
  401.     if (toupper(s1[k]) > toupper(s2[k])) return k + 1;
  402.     }
  403.     return s2[k] ? -k - 1 : 0;
  404. }
  405.  
  406. int strncmp2(s1, s2, n)
  407. char s1[], s2[];
  408. int n;
  409. /*Compares s1 and s2 up to character <n> without regard to case*/
  410. {
  411.     int k;
  412.     for (k = 0; k<n && s1[k]; ++k)
  413.     {
  414.     if (toupper(s1[k]) < toupper(s2[k])) return -k - 1;
  415.     if (toupper(s1[k]) > toupper(s2[k])) return k + 1;
  416.     }
  417.     return k<n && s2[k] ? -k - 1 : 0;
  418. }
  419.  
  420. char *nbfgets(c)
  421. ConnPtr c;
  422. {
  423.     char *retVal;
  424.  
  425.     retVal = (char *) 0;
  426.  
  427.     errno = 0;
  428.  
  429.     while (!retVal && (1 == read(c -> sock, &(c->buf[c->bufi]),1)))
  430.     {
  431. #ifdef DEBUG
  432.     if (isprint(c->buf[c->bufi]))
  433.         fprintf(stderr, "...(%c)\n", c->buf[c->bufi]);
  434.     else
  435.         fprintf(stderr, "---(\\%o)\n", c->buf[c->bufi]);
  436. #endif
  437.     if ((c->buf[c->bufi] == '\n' && (c->bufi==0 || c->buf[c->bufi-1]!='\\'))
  438.         || c->buf[c->bufi] == '\0')
  439.     {
  440.         c->buf[++(c->bufi)] = '\0';
  441.         c->bufi = 0;
  442.         retVal = c->buf;
  443.     }
  444.     else
  445.     {
  446.         c->bufi++;
  447.     }
  448.  
  449.     if (errno)
  450.     {
  451.         if (errno != lasterror)
  452.         {
  453.         fprintf(stderr, "error #%d in socket descriptor\n", errno, c->sock);
  454. #ifdef PERROR
  455.         perror("nbfgets");
  456. #endif
  457.         lasterror = errno;
  458.         }
  459.         if ((errno != EWOULDBLOCK) && (errno != EAGAIN) && (errno != EINTR))
  460.         {
  461.         fprintf(stderr, "Yanking someone's connection\n");
  462.         if (errno == EBADF)
  463.         {
  464.             close(c -> sock);
  465.         }
  466.         else
  467.         {
  468.             CloseSocket(c);
  469.         }
  470.         DeleteConnectionRecord(c);
  471.         }
  472.         errno = 0;
  473.     }
  474.     }
  475.     return retVal;
  476. }
  477.  
  478. char *CopyScianString(l, s)
  479. char *l, *s;
  480. {
  481.     char *lPtr, *sPtr;
  482.     int notdone;
  483.  
  484.     lPtr = l;
  485.     sPtr = s;
  486.  
  487.     /* skip whitespace */
  488.     while (isspace(*sPtr))
  489.     {
  490.     ++sPtr;
  491.     }
  492.  
  493.     notdone = true;
  494.     while(notdone && sPtr - s < MYBUFSIZ)
  495.     {
  496.     switch (*sPtr)
  497.     {
  498.         case ' ': case '\n': case '\t': case '\0': case '\r':
  499.         notdone = false;
  500.         *lPtr = '\0';
  501.         break;
  502.         case '\\':
  503.         *lPtr++ = *sPtr;
  504.         ++sPtr;
  505.         *lPtr++ = *sPtr;
  506.         break;
  507.         default:
  508.         *lPtr++ = *sPtr;
  509.         break;
  510.     }
  511.     if (notdone)
  512.         ++sPtr;
  513.     }
  514.     if (lPtr == l)
  515.     {
  516.     /* didn't write anything! */
  517.     return (char *) 0;
  518.     }
  519.     return sPtr;
  520. }
  521.  
  522. /* write a string to a socket. Force a \n onto the end */
  523. void PutSock(conn, s)
  524. ConnPtr conn;
  525. char *s;
  526. {
  527.     int tmp, sofar;
  528.  
  529.     if (conn->sock < 0)
  530.     {
  531.     fprintf(stderr, "tried to write to bad file descriptor!\n");
  532.     return;
  533.     }
  534.  
  535.     if (conn -> state != CONNECTED)
  536.     {
  537.     fprintf(stderr, "write with socket state = %d\n", conn -> state);
  538.     return;
  539.     }
  540.  
  541.     errno = 0;
  542.  
  543.     writen(conn -> sock, s, strlen(s));
  544.  
  545.     if (errno)
  546.     {
  547. #ifdef PERROR
  548.     perror("PutSock");
  549. #endif
  550.     conn -> flags = conn -> flags | ND_FLAGS_STREAMERROR;
  551.     errno = 0;
  552.     }
  553. }
  554.  
  555. typedef struct Message {
  556.     /* int sockNum; */
  557.     ConnPtr conn;
  558.     struct Message *next;
  559.     char s;
  560. } *MessagePtr;
  561.  
  562. MessagePtr messageList = (MessagePtr) 0;
  563.  
  564. void DeferMessage(c, s)
  565. /* int cNum; */
  566. ConnPtr c;
  567. char *s;
  568. {
  569.     MessagePtr tmp, *runner;
  570.  
  571.     /* allocate space for the structure (-1 byte) plus the string (+1 byte) */
  572.     tmp = malloc(sizeof(struct Message) + strlen(s));
  573.     tmp->next = (struct Message *) 0;
  574.     tmp->conn = c;
  575.     strcpy(&(tmp->s), s);
  576.  
  577.     /*stick message on the end of the list */
  578.     runner = &messageList;
  579.     while(*runner)
  580.     runner = &((*runner)->next);
  581.  
  582.     *runner = tmp;
  583. }
  584.  
  585. int DoDeferredMessage()
  586. {
  587.     MessagePtr msg;
  588.  
  589.     if (!messageList)
  590.     return false;
  591.  
  592.     msg = messageList;
  593.     messageList = messageList -> next;
  594.  
  595.     PutSock(msg -> conn, &(msg -> s));
  596.  
  597.     return true;
  598. }
  599.  
  600. Time Clock()
  601. {
  602. #if MACHINE == IRIS4D
  603.     return ((double) times(×Buffer)) / HZ;
  604. #else
  605. #if MACHINE == CRAYYMP
  606.     return ((double) times(×Buffer)) / CLK_TCK;
  607. #else
  608.     return ((double) times(×Buffer)) / CLK_TCK;
  609. #endif
  610. #endif
  611. }
  612.  
  613. ProcessPtr FindProcess(num)
  614. int num;
  615. {
  616.     ProcessPtr tmp;
  617.  
  618.     tmp = processes;
  619.  
  620.     while (tmp)
  621.     {
  622.     if (tmp->procNum == num)
  623.     {
  624.         return tmp;
  625.     }
  626.     tmp = tmp->next;
  627.     }
  628.     return (ProcessPtr) 0;
  629. }
  630.  
  631. int DeleteProcess(num)
  632. int num;
  633. {
  634.     ProcessPtr *runner, tmp;
  635.     ObjRecPtr objRunner;
  636.     SockListPtr sockRunner;
  637.  
  638.     runner = &processes;
  639.  
  640.     while (*runner)
  641.     {
  642.     if ((*runner)->procNum == num)
  643.     {
  644.         tmp = *runner;
  645.         *runner = (*runner) -> next;
  646.         objRunner = tmp -> objectList;
  647.         while (objRunner)
  648.         {
  649.         free (objRunner);
  650.         objRunner = objRunner -> next;
  651.         }
  652.         sockRunner = tmp -> keepAdvised;
  653.         while (sockRunner)
  654.         {
  655.         free (sockRunner);
  656.         sockRunner = sockRunner -> next;
  657.         }
  658.         free (tmp);
  659.         return 0;
  660.     }
  661.     runner = &((*runner)->next);
  662.     }
  663. #ifdef DEBUG
  664.     fprintf(stderr, "DeleteProcess: process number %d does not exist\n", num);
  665. #endif
  666.     return -1;
  667. }
  668.  
  669. int AddProcess(num, sockNum, name)
  670. int num;
  671. int sockNum;
  672. char *name;
  673. {
  674.     ProcessPtr procPtr;
  675.  
  676.     if (FindProcess(num))
  677.     {
  678.     /* it's already there */
  679. #ifdef DEBUG
  680.     fprintf(stderr, "Tried to duplicate process number\n");
  681. #endif
  682.     return -1;
  683.     }
  684.     /* it wasn't already there, add new process. */
  685.     procPtr = (ProcessPtr) malloc(sizeof(ProcessStruct)+(name?strlen(name):0));
  686.     procPtr -> procNum = num;
  687.     procPtr -> sockNum = sockNum;
  688.     procPtr -> lastAccess = Clock();
  689.     procPtr -> next = processes;
  690.     procPtr -> objectList = (ObjRecPtr) 0;
  691.     procPtr -> keepAdvised = (SockListPtr) 0;
  692.     if (name)
  693.     strcpy(procPtr -> procName, name);
  694.     else
  695.     procPtr -> procName[0] = '\0';
  696.     processes = procPtr;
  697. #ifdef DEBUG
  698.     fprintf(stderr, "added process #%d\n", num);
  699. #endif
  700.     return 0;
  701. }
  702.  
  703. ObjRecPtr FindObject(procNum, objNum)
  704. int procNum;
  705. unsigned long objNum;
  706. {
  707.     ProcessPtr procPtr;
  708.     ObjRecPtr runner;
  709.  
  710.     if (!(procPtr = FindProcess(procNum)))
  711.     {
  712.     return (ObjRecPtr) 0;
  713.     }
  714.  
  715.     runner = procPtr -> objectList;
  716.     while (runner)
  717.     {
  718.     if (runner -> objectNum == objNum)
  719.     {
  720.         return runner;
  721.     }
  722.     runner = runner -> next;
  723.     }
  724.     return (ObjRecPtr) 0;
  725. }
  726.  
  727. int DeleteObject(procNum, objNum)
  728. int procNum;
  729. unsigned long objNum;
  730. {
  731.     ProcessPtr procPtr;
  732.     ObjRecPtr *runner;
  733.  
  734.     if (!(procPtr = FindProcess(procNum)))
  735.     {
  736.     return -1;
  737.     }
  738.  
  739.     runner = &(procPtr -> objectList);
  740.     while (*runner)
  741.     {
  742.     if ((*runner) -> objectNum == objNum)
  743.     {
  744.         ObjRecPtr tmp;
  745.  
  746.         tmp = *runner;
  747.         *runner = (*runner) -> next;
  748.         free(tmp);
  749.         return 0;
  750.     }
  751.     runner = &((*runner) -> next);
  752.     }
  753.  
  754.     return -1;
  755. }
  756.  
  757. int AddObject(procNum, objNum, iconNum, objName)
  758. int procNum;
  759. unsigned long objNum;
  760. int iconNum;
  761. char *objName;
  762. {
  763.     ProcessPtr procPtr;
  764.     ObjRecPtr tmp;
  765.  
  766.     if (!(procPtr = FindProcess(procNum)))
  767.     {
  768.     return -1;
  769.     }
  770.  
  771.     if (FindObject(procNum, objNum))
  772.     {
  773.     /* object already existed? */
  774.     return -1;
  775.     }
  776.  
  777.     tmp = malloc(sizeof(struct ORStruct) + (objName ? strlen(objName) : 0));
  778.     tmp -> objectNum = objNum;
  779.     tmp -> iconNum = iconNum;
  780.     strcpy(tmp -> objectName, objName);
  781.     tmp -> next = procPtr -> objectList;
  782.     procPtr -> objectList = tmp;
  783.  
  784.     return 0;
  785. }
  786.  
  787. #if 0
  788. static u_short SocketPort(c)
  789. /*Returns the port for the socket*/
  790. ConnPtr c;
  791. {
  792.     return htons((u_short) c -> sockNum);
  793. }
  794. #endif
  795.  
  796. void InterpretSocketCommand(c, s)
  797. ConnPtr c;
  798. char *s;
  799. {
  800.     int procNum;
  801.     unsigned long objNum;
  802.     int objIconNum;
  803.     ProcessPtr procPtr;
  804.     ObjRecPtr objPtr;
  805.     SockListPtr sockPtr;
  806.     char procName[MYBUFSIZ], objName[MYBUFSIZ];
  807.     char *cPtr;
  808.     int chri;
  809.  
  810.     if (4 != ND_CMD_STR_LENGTH)
  811.     {
  812.     fprintf(stderr, "ScianNetDaemon: Internal Error!\n");
  813.     }
  814.  
  815.     if (strlen(s) < ND_CMD_STR_LENGTH)
  816.     {
  817. #ifdef DEBUG
  818.     fprintf(stderr, "ScianNetDaemon: socket command format error\n");
  819. #endif
  820.     sprintf(tempStr, "%s\n", ND_ERROR);
  821.     PutSock(c, tempStr);
  822.     return;
  823.     }
  824.     
  825.     if (0 == strncmp2(s, ND_REG_PROCESS, ND_CMD_STR_LENGTH))
  826.     {
  827.     ConnPtr runner;
  828.     int sockNum;
  829.  
  830.     /* should be a process number following */
  831.     if (2 != sscanf (s + 4, "%d%d%n", &procNum, &sockNum, &chri))
  832.     {
  833. #ifdef DEBUG
  834.         fprintf(stderr, "Error: no process number\n%s\n", s);
  835. #endif
  836.         sprintf(tempStr, "%s\n", ND_ERROR);
  837.         PutSock(c, tempStr);
  838.         return;
  839.     }
  840.  
  841.     if (!CopyScianString(procName, s + 4 + chri))
  842.     {
  843.         sprintf(procName, "proc%d", procNum);
  844.     }
  845.     else if (procName[strlen(procName) - 1] == '\\')
  846.     {
  847.         /* more string on the next line */
  848.     }
  849.  
  850.     if(AddProcess(procNum, sockNum, procName))
  851.     {
  852. #ifdef DEBUG
  853.         fprintf(stderr, "process #%d already existed\n", procNum);
  854. #endif
  855.         sprintf(tempStr, "%s\n", ND_ERROR);
  856.         PutSock(c, tempStr);
  857.         return;
  858.     }
  859.  
  860.     runner = connList;
  861.     sprintf(tempStr, "%s %d %s\n", ND_INFO_LIVE_PROCESS,
  862.         sockNum, procName);
  863.     while (runner)
  864.     {
  865.         if (runner -> flags & ND_FLAGS_KEEPADVISED)
  866.         {
  867.         DeferMessage(runner, tempStr);
  868.         }
  869.         runner = runner -> next;
  870.     }
  871.  
  872.     }
  873.     else if (0 == strncmp2(s, ND_UNREG_PROCESS, ND_CMD_STR_LENGTH))
  874.     {
  875.     /* should be a process number following */
  876.     if (1 != sscanf (s + 4, "%d", &procNum))
  877.     {
  878. #ifdef DEBUG
  879.         fprintf(stderr, "Error: no process number\n%s\n", s);
  880. #endif
  881.         sprintf(tempStr, "%s\n", ND_ERROR);
  882.         PutSock(c, tempStr);
  883.         return;
  884.     }
  885.  
  886.     if (procPtr = FindProcess(procNum))
  887.     {
  888.         sprintf(tempStr, "%s %d %s\n", ND_INFO_DEAD_PROCESS,
  889.         procPtr -> sockNum, procPtr -> procName);
  890.     }
  891.  
  892.     if (DeleteProcess(procNum) != -1)
  893.     {
  894.         ConnPtr runner;
  895.  
  896.         runner = connList;
  897.         while (runner)
  898.         {
  899.         if (runner -> flags & ND_FLAGS_KEEPADVISED)
  900.         {
  901.             DeferMessage(runner, tempStr);
  902.         }
  903.         runner = runner -> next;
  904.         }
  905.     }
  906.     }
  907.     else if (0 == strncmp2(s, ND_INQ_PROCESS, ND_CMD_STR_LENGTH))
  908.     {
  909.     /* should be etc., etc., etc.. */
  910.     if (1 != sscanf (s + 4, "%d", &procNum))
  911.     {
  912. #ifdef DEBUG
  913.         fprintf(stderr, "Error: no process number\n%s\n", s);
  914. #endif
  915.         sprintf(tempStr, "%s\n", ND_ERROR);
  916.         PutSock(c, tempStr);
  917.         return;
  918.     }
  919.  
  920.     if (!(procPtr = FindProcess(procNum)))
  921.     {
  922. #ifdef DEBUG
  923.         fprintf(stderr, "Error: Process #%d not found\n", procNum);
  924. #endif
  925.         sprintf(tempStr, "%s\n", ND_ERROR);
  926.         PutSock(c, tempStr);
  927.         return;
  928.     }
  929.  
  930.     sprintf(tempStr, "%s %d %s\n", ND_INFO_LIVE_PROCESS, procPtr -> sockNum,
  931.         procPtr -> procName);
  932.     DeferMessage(c, tempStr);
  933.  
  934.     }
  935.     else if (0 == strncmp2(s, ND_LIST_PROCESSES, ND_CMD_STR_LENGTH))
  936.     {
  937.     ProcessPtr runner;
  938.  
  939.     runner = processes;
  940.     while (runner)
  941.     {
  942.         sprintf(tempStr, "%s %d %s\n", ND_INFO_LIVE_PROCESS,
  943.         runner -> sockNum, runner -> procName);
  944.         DeferMessage(c, tempStr);
  945.         runner = runner -> next;
  946.     }
  947.     }
  948.     else if (0 == strncmp2(s, ND_UPDATE_PROCESSES, ND_CMD_STR_LENGTH))
  949.     {
  950.     ProcessPtr runner;
  951.  
  952.     runner = processes;
  953.     while (runner)
  954.     {
  955.         sprintf(tempStr, "%s %d %s\n", ND_INFO_LIVE_PROCESS,
  956.         runner -> sockNum, runner -> procName);
  957.         DeferMessage(c, tempStr);
  958.         runner = runner -> next;
  959.     }
  960.     c -> flags = c -> flags | ND_FLAGS_KEEPADVISED;
  961.     }
  962.     else if (0 == strncmp2(s, ND_NOT_UPDATE_PROCESSES, ND_CMD_STR_LENGTH))
  963.     {
  964.     c -> flags = c -> flags & ~ND_FLAGS_KEEPADVISED;
  965.     }
  966.     else if (0 == strncmp2(s, ND_REG_OBJECT, ND_CMD_STR_LENGTH))
  967.     {
  968.     SockListPtr runner;
  969.  
  970.     /* should be a process number and object number following */
  971.     if (2 != sscanf (s + 4, "%d%d%n", &procNum, &objNum, &chri))
  972.     {
  973. #ifdef DEBUG
  974.         fprintf(stderr, "Error: process and object numbers expected\n%s\n", s);
  975. #endif
  976.         sprintf(tempStr, "%s\n", ND_ERROR);
  977.         PutSock(c, tempStr);
  978.         return;
  979.     }
  980.     if (!(cPtr = CopyScianString(objName, s + 4 + chri)))
  981.     {
  982.         sprintf(objName, "obj%d", objNum);
  983.     }
  984.  
  985.     if (cPtr)
  986.     {
  987.         if (1 != sscanf (cPtr, "%d", &objIconNum))
  988.         {
  989.         objIconNum = ICONUNKNOWN;
  990.         }
  991.     }
  992.     else
  993.     {
  994.         objIconNum = ICONUNKNOWN;
  995.     }
  996.  
  997.     if (!(procPtr = FindProcess(procNum)))
  998.     {
  999. #ifdef DEBUG
  1000.         fprintf (stderr, "no process #%d\n", procNum);
  1001. #endif
  1002.         sprintf(tempStr, "%s\n", ND_ERROR);
  1003.         PutSock(c, tempStr);
  1004.         return;
  1005.     }
  1006.  
  1007.     if(-1 == AddObject(procNum, objNum, objIconNum, objName))
  1008.     {
  1009. #ifdef DEBUG
  1010.         fprintf(stderr, "Couldn't add object %ld to process %d\n", objNum, procNum);
  1011. #endif
  1012.         sprintf(tempStr, "%s\n", ND_ERROR);
  1013.         PutSock(c, tempStr);
  1014.         return;
  1015.     }
  1016.  
  1017.     runner = procPtr -> keepAdvised;
  1018.     sprintf(tempStr, "%s %d %d %s %d\n", ND_INFO_LIVE_OBJECT,
  1019.         procNum, objNum, objName, objIconNum);
  1020.     while (runner)
  1021.     {
  1022.         DeferMessage(runner -> conn, tempStr);
  1023.         runner = runner -> next;
  1024.     }
  1025.     }
  1026.     else if (0 == strncmp2(s, ND_UNREG_OBJECT, ND_CMD_STR_LENGTH))
  1027.     {
  1028.     /* should be a process number and object number following */
  1029.     if (2 != sscanf (s + 4, "%d%d", &procNum, &objNum))
  1030.     {
  1031. #ifdef DEBUG
  1032.         fprintf(stderr, "Error: process and object numbers expected\n%s\n", s);
  1033. #endif
  1034.         sprintf(tempStr, "%s\n", ND_ERROR);
  1035.         PutSock(c, tempStr);
  1036.         return;
  1037.     }
  1038.  
  1039.     if (!(procPtr = FindProcess(procNum)))
  1040.     {
  1041. #ifdef DEBUG
  1042.         fprintf (stderr, "no process #%d\n", procNum);
  1043. #endif
  1044.         sprintf(tempStr, "%s\n", ND_ERROR);
  1045.         PutSock(c, tempStr);
  1046.         return;
  1047.     }
  1048.  
  1049.     if(-1 == DeleteObject(procNum, objNum))
  1050.     {
  1051. #ifdef DEBUG
  1052.         fprintf(stderr, "Error deleting object %ld from process %d\n", objNum, procNum);
  1053. #endif
  1054.         sprintf(tempStr, "%s\n", ND_ERROR);
  1055.         PutSock(c, tempStr);
  1056.         return;
  1057.     }
  1058.  
  1059.     {
  1060.         SockListPtr runner;
  1061.  
  1062.         runner = procPtr -> keepAdvised;
  1063.         sprintf(tempStr, "%s %d %d\n", ND_INFO_DEAD_OBJECT, procNum, objNum);
  1064.         while (runner)
  1065.         {
  1066.         DeferMessage(runner -> conn, tempStr);
  1067.         runner = runner -> next;
  1068.         }
  1069.     }
  1070.     }
  1071.     else if (0 == strncmp2(s, ND_INQ_OBJECT, ND_CMD_STR_LENGTH))
  1072.     {
  1073.     /* should be a process number and object number following */
  1074.     if (2 != sscanf (s + 4, "%d%d", &procNum, &objNum))
  1075.     {
  1076. #ifdef DEBUG
  1077.         fprintf(stderr, "Error: process and object numbers expected\n%s\n", s);
  1078. #endif
  1079.         sprintf(tempStr, "%s\n", ND_ERROR);
  1080.         PutSock(c, tempStr);
  1081.         return;
  1082.     }
  1083.  
  1084.     if (!(procPtr = FindProcess(procNum)))
  1085.     {
  1086. #ifdef DEBUG
  1087.         fprintf (stderr, "no process #%d\n", procNum);
  1088. #endif
  1089.         sprintf(tempStr, "%s\n", ND_ERROR);
  1090.         PutSock(c, tempStr);
  1091.         return;
  1092.     }
  1093.  
  1094.     if(!(objPtr = FindObject(procNum, objNum)))
  1095.     {
  1096. #ifdef DEBUG
  1097.         fprintf(stderr, "Couldn't find object %ld in process %d\n",
  1098.             objNum, procNum);
  1099. #endif
  1100.         sprintf(tempStr, "%s\n", ND_ERROR);
  1101.         PutSock(c, tempStr);
  1102.         return;
  1103.     }
  1104.     else
  1105.     {
  1106.         sprintf(tempStr, "%s %d %d %s %d\n", ND_INFO_LIVE_OBJECT,
  1107.         procNum, objNum, objPtr -> objectName, objPtr -> iconNum);
  1108.         DeferMessage(c, tempStr);
  1109.     }
  1110.     }
  1111.     else if (0 == strncmp2(s, ND_LIST_OBJECTS, ND_CMD_STR_LENGTH))
  1112.     {
  1113.     /* should be a process number number following */
  1114.     if (1 != sscanf (s + 4, "%d", &procNum))
  1115.     {
  1116. #ifdef DEBUG
  1117.         fprintf(stderr, "Error: process number expected\n%s\n", s);
  1118. #endif
  1119.         sprintf(tempStr, "%s\n", ND_ERROR);
  1120.         PutSock(c, tempStr);
  1121.         return;
  1122.     }
  1123.  
  1124.     if (!(procPtr = FindProcess(procNum)))
  1125.     {
  1126. #ifdef DEBUG
  1127.         fprintf (stderr, "no process #%d\n", procNum);
  1128. #endif
  1129.         sprintf(tempStr, "%s\n", ND_ERROR);
  1130.         PutSock(c, tempStr);
  1131.         return;
  1132.     }
  1133.  
  1134.     /* advise of objects that are already listed */
  1135.     objPtr = procPtr -> objectList;
  1136.     while (objPtr)
  1137.     {
  1138.         sprintf(tempStr, "%s %d %d %s %d\n", ND_INFO_LIVE_OBJECT, procNum,
  1139.         objPtr -> objectNum, objPtr -> objectName, objPtr -> iconNum);
  1140.         DeferMessage(c, tempStr);
  1141.         objPtr = objPtr -> next;
  1142.     }
  1143.     }
  1144.     else if (0 == strncmp2(s, ND_UPDATE_OBJECTS, ND_CMD_STR_LENGTH))
  1145.     {
  1146.     /* should be a process number number following */
  1147.     if (1 != sscanf (s + 4, "%d", &procNum))
  1148.     {
  1149. #ifdef DEBUG
  1150.         fprintf(stderr, "Error: process number expected\n%s\n", s);
  1151. #endif
  1152.         sprintf(tempStr, "%s\n", ND_ERROR);
  1153.         PutSock(c, tempStr);
  1154.         return;
  1155.     }
  1156.  
  1157.     if (!(procPtr = FindProcess(procNum)))
  1158.     {
  1159. #ifdef DEBUG
  1160.         fprintf (stderr, "no process #%d\n", procNum);
  1161. #endif
  1162.         sprintf(tempStr, "%s\n", ND_ERROR);
  1163.         PutSock(c, tempStr);
  1164.         return;
  1165.     }
  1166.  
  1167.     sockPtr = malloc(sizeof(struct SLStruct));
  1168.     sockPtr -> conn = c;
  1169.     sockPtr -> next = procPtr -> keepAdvised;
  1170.     procPtr -> keepAdvised = sockPtr;
  1171.  
  1172.     /* advise of objects that are already listed */
  1173.     objPtr = procPtr -> objectList;
  1174.     while (objPtr)
  1175.     {
  1176.         sprintf(tempStr, "%s %d %d %s %d\n", ND_INFO_LIVE_OBJECT, procNum,
  1177.         objPtr -> objectNum, objPtr -> objectName, objPtr -> iconNum);
  1178.         DeferMessage(c, tempStr);
  1179.         objPtr = objPtr -> next;
  1180.     }
  1181.     }
  1182.     else if (0 == strncmp2(s, ND_NOT_UPDATE_OBJECTS, ND_CMD_STR_LENGTH))
  1183.     {
  1184.     SockListPtr *runner;
  1185.     /* should be a process number number following */
  1186.     if (1 != sscanf (s + 4, "%d", &procNum))
  1187.     {
  1188. #ifdef DEBUG
  1189.         fprintf(stderr, "Error: process number expected\n%s\n", s);
  1190. #endif
  1191.         sprintf(tempStr, "%s\n", ND_ERROR);
  1192.         PutSock(c, tempStr);
  1193.         return;
  1194.     }
  1195.  
  1196.     if (!(procPtr = FindProcess(procNum)))
  1197.     {
  1198. #ifdef DEBUG
  1199.         fprintf (stderr, "no process #%d\n", procNum);
  1200. #endif
  1201.         sprintf(tempStr, "%s\n", ND_ERROR);
  1202.         PutSock(c, tempStr);
  1203.         return;
  1204.     }
  1205.  
  1206.     runner = &(procPtr -> keepAdvised);
  1207.     while (*runner)
  1208.     {
  1209.         if ((*runner) -> conn == c)
  1210.         {
  1211.         SockListPtr tmp;
  1212.         tmp = *runner;
  1213.         *runner = (*runner) -> next;
  1214.         free (tmp);
  1215.         break;
  1216.         }
  1217.         runner = &((*runner) -> next);
  1218.     }
  1219.     }
  1220.     else if (0 == strncmp2(s, ND_CLOSE, ND_CMD_STR_LENGTH))
  1221.     {
  1222.         if (IsMainConn(c))
  1223.         {
  1224.             close(c->sock); c->sock = -1;
  1225.             c->state = LISTENING;
  1226.         }
  1227.         else
  1228.         {
  1229.             CloseSocket(c);
  1230.             DeleteConnectionRecord(c);
  1231.         }
  1232.     }
  1233.     else if (0 == strncmp2(s, ND_EXIT, ND_CMD_STR_LENGTH))
  1234.     {
  1235. #ifdef DEBUG
  1236.     fprintf(stderr, "got exit directive, byebye\n");
  1237. #endif
  1238.     CloseAll();
  1239.     exit (0);
  1240.     }
  1241.     else
  1242.     {
  1243. #ifdef DEBUG
  1244.     fprintf(stderr, "Error: unparseable\n%s\n", s);
  1245. #endif
  1246.     sprintf(tempStr, "%s\n", ND_ERROR);
  1247.     PutSock(c, tempStr);
  1248.     return;
  1249.     }
  1250. }
  1251.  
  1252. #define COMMAND_SIZ 256
  1253.  
  1254.  
  1255. int IdleSocket(c)
  1256. ConnPtr c;
  1257. /* My version of idling the sockets */
  1258. {
  1259.     struct sockaddr_in inSocketAddr;
  1260.     int inSocket;
  1261.     int tmp;
  1262.     ConnPtr tmpConn;
  1263.  
  1264. /* temporary? */
  1265.     char *tmpPtr;
  1266.  
  1267.     if (!c)
  1268.     {
  1269.     fprintf(stderr, "Null Connection pointer!\n");
  1270.     return false;
  1271.     }
  1272.  
  1273.     switch (c->state)
  1274.     {
  1275.     case NOTLISTENING:
  1276.         if (FindSocket(c) < 0)
  1277.         {
  1278. #ifdef DEBUG
  1279.         fprintf(stderr, "FindSocket() failed!\n");
  1280. #endif
  1281.         if (IsMainConn(c)) sleep(1);
  1282.         return false;
  1283.         }
  1284.  
  1285.         fprintf(stderr, "connected\n");
  1286.         c->state = LISTENING;
  1287.         break;
  1288.     case LISTENING:
  1289.         /* waiting for a phone call */
  1290.         c->sock = accept(c->template, (struct sockaddr *) 0, (int *) 0);
  1291.         if (c->sock != -1)
  1292.         {
  1293. #ifdef PAUSE
  1294.         /* ioctl(c->sock, I_SETSIG, S_INPUT); */
  1295.         fcntl(c->sock, F_SETOWN, getpid());
  1296.         fcntl(c->sock, F_SETFL,
  1297.             fcntl(c->sock, F_GETFL) | FASYNC);
  1298. #endif
  1299.         /* set up main connection */
  1300. /*
  1301.         if (IsMainConn(c))
  1302.         {
  1303.             c->state = VALIDATING;
  1304.         }
  1305.         else
  1306.         {
  1307.             c->state = CONNECTED;
  1308.             sprintf(tempStr, "%s %s\n", ND_INFO_VERSION,
  1309.             ND_NET_DAEMON_VERSION);
  1310.             DeferMessage(c, tempStr);
  1311.             
  1312.         }
  1313. */
  1314.         c -> state = VALIDATING;
  1315.         /* version message moved down to case VALIDATING */
  1316.         }
  1317.         else
  1318.         {
  1319.         return false;
  1320.         }
  1321.         break;
  1322.     case VALIDATING:
  1323.         /* one ringy dingy... */
  1324.  
  1325.         if (tmpPtr = nbfgets(c))
  1326.         {
  1327. #ifdef DEBUG
  1328.         fprintf(stderr, "tmpPtr = %s\n", tmpPtr);
  1329. #endif
  1330.         if (0 != strncmp2(tmpPtr, ND_PASSWORD, ND_CMD_STR_LENGTH))
  1331.         {
  1332.             return false;
  1333.         }
  1334.         fprintf(stderr, "accepted and validated connection\n");
  1335.         tmpConn = NewConn();
  1336.         AddConnectionRecord(tmpConn);
  1337.         tmpConn -> state = CONNECTED;
  1338.         tmpConn -> sock = c -> sock;
  1339.  
  1340.         sprintf(tempStr, "%s %s\n", ND_INFO_VERSION,
  1341.             ND_NET_DAEMON_VERSION);
  1342.         DeferMessage(tmpConn, tempStr);
  1343.  
  1344.         c -> sock = -1;
  1345.         c->state = LISTENING;
  1346.         return true;
  1347.         }
  1348.         else
  1349.         {
  1350.         return false;
  1351.         }
  1352.         break;
  1353.     case CONNECTED:
  1354.         if (tmpPtr = nbfgets(c))
  1355.         {
  1356. #ifdef DEBUG
  1357.         fprintf(stderr, "tmpPtr = %x, *tmpPtr: %s\n", tmpPtr, tmpPtr);
  1358. #endif
  1359.         InterpretSocketCommand(c, tmpPtr);
  1360.         }
  1361.         else
  1362.         {
  1363.         return false;
  1364.         }
  1365.         break;
  1366.     case TRANSFERRING:
  1367.         /* forwarding your call to the appropriate party */
  1368.         break;
  1369.     }
  1370.     return true;
  1371. }
  1372.  
  1373. /* ConnPtr connTracker = (ConnPtr) 0; */
  1374.  
  1375. Time lastActionTime;
  1376.  
  1377. void IdleAllSockets()
  1378. {
  1379.     ConnPtr connTracker;
  1380.     int didSomething = 0;
  1381.  
  1382.     didSomething += IdleSocket(mainConn);
  1383. /*
  1384.     if (!connTracker)
  1385.     {
  1386.     connTracker = connList;
  1387.     }
  1388. */
  1389.     connTracker = connList;
  1390.     /* if */ while (connTracker)
  1391.     {
  1392.     didSomething += IdleSocket(connTracker);
  1393.     connTracker = connTracker -> next;
  1394.     }
  1395.     if (!didSomething)
  1396.     {
  1397.     didSomething += DoDeferredMessage();
  1398.     }
  1399.  
  1400.     if (didSomething)
  1401.     {
  1402.     lastActionTime = Clock();
  1403.     }
  1404.  
  1405.     /* go out to lunch if no activity in the last ATTENTION_SPAN secs*/
  1406.     if (Clock() > lastActionTime + ATTENTION_SPAN && !didSomething)
  1407.     {
  1408. #ifdef PAUSE
  1409.     sigblock(sigmask(SIGIO));
  1410.     sigpause(sigmask(SIGIO));
  1411.     fprintf(stderr, "handler was called %d times\n", handlerCount - oldHandlerCount);
  1412.     oldHandlerCount = handlerCount;
  1413.     sigsetmask(0);
  1414. #else
  1415.     sleep(1);
  1416. #endif
  1417.     }
  1418.  
  1419.     if (timeOut > 0.0 && Clock() > lastActionTime + timeOut && !didSomething)
  1420.     {
  1421.     /* we've been idle for too long, time to go home */
  1422.     fprintf(stderr, "No activity for %d seconds, NetDaemon exiting\n",
  1423.         (int) (Clock() - lastActionTime));
  1424.     exit(0);
  1425.     }
  1426. }
  1427.  
  1428. void CommandLineError(name)
  1429. char *name;
  1430. {
  1431.     fprintf(stderr, "error on command line\n");
  1432.     fprintf(stderr, "usage: %s [-t <timeout>] [-s <socketnumber>] [-l <blocklength>]\n", name);
  1433.     exit (-1);
  1434. }
  1435.  
  1436. ParseArgs(argc, argv)
  1437. int argc;
  1438. char *argv[1];
  1439. {
  1440.     int i;
  1441.     char *cPtr;
  1442.  
  1443.     socketBlockLength = ND_SOCKET_BLOCK_LENGTH; /*may be overridden */
  1444.     baseSocketNumber = ND_BASE_SOCKET_NUMBER; /*may be overridden on cmd line*/
  1445.  
  1446.     for (i = 1; i < argc; ++i)
  1447.     {
  1448.     cPtr = argv[i];
  1449.     if (*cPtr == '-')
  1450.     {
  1451.         switch(*++cPtr)
  1452.         {
  1453.         case 't':
  1454.             if (1 != sscanf(++cPtr, "%lf", &timeOut))
  1455.             {
  1456.             if ((i + 1 >= argc) || (1 != sscanf(argv[i+1],
  1457.                         "%lf", &timeOut)))
  1458.             {
  1459.                 fprintf(stderr, "integer expected after -t\n");
  1460.                 CommandLineError(argv[0]);
  1461.             }
  1462.             else
  1463.             {
  1464.                 ++i;
  1465.             }
  1466.             }
  1467.             break;
  1468.         case 's':
  1469.             if (1 != sscanf(++cPtr, "%d", &baseSocketNumber))
  1470.             {
  1471.             if ((i + 1 >= argc) || (1 != sscanf(argv[i+1],
  1472.                         "%d", &baseSocketNumber)))
  1473.             {
  1474.                 fprintf(stderr, "integer expected after -s\n");
  1475.                 CommandLineError(argv[0]);
  1476.             }
  1477.             else
  1478.             {
  1479.                 ++i;
  1480.             }
  1481.             }
  1482.             break;
  1483.         case 'l':
  1484.             if (1 != sscanf(++cPtr, "%d", &socketBlockLength))
  1485.             {
  1486.             if ((i + 1 >= argc) || (1 != sscanf(argv[i+1],
  1487.                         "%d", &socketBlockLength)))
  1488.             {
  1489.                 fprintf(stderr, "integer expected after -l\n");
  1490.                 CommandLineError(argv[0]);
  1491.             }
  1492.             else
  1493.             {
  1494.                 ++i;
  1495.             }
  1496.             }
  1497.             break;
  1498.         default:
  1499.             fprintf(stderr, "unexpected argument\n");
  1500.             CommandLineError(argv[0]);
  1501.             break;
  1502.         }
  1503.     }
  1504.     else
  1505.     {
  1506.         fprintf(stderr, "error in argument\n");
  1507.         CommandLineError(argv[0]);
  1508.     }
  1509.     }
  1510. }
  1511.  
  1512. void SanityCheck()
  1513. {
  1514.     ConnPtr runner1, runner2;
  1515.  
  1516.     runner1 = connList;
  1517.     while (runner1)
  1518.     {
  1519.     runner2 = runner1 -> next;
  1520.     while (runner2)
  1521.     {
  1522.         if (runner1 -> sock == runner2 -> sock)
  1523.         {
  1524.         fprintf(stderr, "shared file descriptor! %d.\n", runner1 -> sock);
  1525.         }
  1526.     }
  1527.     }
  1528. }
  1529.  
  1530. #define SANITYCHECKINTERVAL 5
  1531.  
  1532. main(argc, argv)
  1533. int argc;
  1534. char *argv[1];
  1535. {
  1536.     Time lastSanityCheck;
  1537.  
  1538. #ifdef PAUSE
  1539. #ifdef BSD_SIGS
  1540.     struct sigvec sv,osv;
  1541.     
  1542.     sv.sv_handler = sigIOHandler;     /* pointer to routine. */
  1543.     sv.sv_mask = 0;              /* no additional signals masked */
  1544.     sv.sv_flags = SV_INTERRUPT;  /* no restarted system calls */
  1545.     sigvec(SIGIO,&sv,&osv);
  1546. #else
  1547. #ifdef SYSV_SIGS
  1548.     signal(SIGIO, sigIOHandler);
  1549. #else
  1550.     Yer up shits creek, bud!;
  1551. #endif /* def SYSV_SIGS */
  1552. #endif /* def BSD_SIGS */
  1553. #endif /* def PAUSE */
  1554.  
  1555. #ifdef ALARM
  1556. #ifdef SYSV_SIGS
  1557.     signal(SIGALRM, sigAlrmHandler);
  1558. #else
  1559. #ifdef BSD_SIGS
  1560.     sv.sv_handler = sigAlrmHandler;     /* pointer to routine. */
  1561.     sv.sv_mask = 0;              /* no additional signals masked */
  1562.     sv.sv_flags = SV_INTERRUPT;  /* no restarted system calls */
  1563.     sigvec(SIGALRM,&sv,&osv);
  1564.  
  1565. #else
  1566.     Need BSD_SIGS or SYSV_SIGS defined!
  1567. #endif /* def BSD_SIGS */
  1568. #endif /* def SYSV_SIGS */
  1569. #endif /* def ALARM */
  1570.  
  1571.     ParseArgs(argc, argv);
  1572.  
  1573.     lastPort = baseSocketNumber;
  1574.  
  1575.     lastActionTime = Clock();
  1576.  
  1577.     mainConn = NewConn();
  1578.     mainConn -> sockNum = baseSocketNumber;
  1579.  
  1580.     proto = getprotobyname("tcp") -> p_proto;
  1581.  
  1582.  
  1583.     for (;;)
  1584.     {
  1585.     IdleAllSockets();
  1586. #ifdef ALARM
  1587.     if (alarmClock)
  1588.     {
  1589.         CloseAll();
  1590.         exit(0);
  1591.     }
  1592. #endif /* def ALARM */
  1593.     if (lastSanityCheck + SANITYCHECKINTERVAL > Clock())
  1594.     {
  1595.         SanityCheck();
  1596.     }
  1597.     }
  1598. }
  1599.